import {Component, Inject, OnDestroy, OnInit, ViewEncapsulation} from '@angular/core';
import {FormBuilder, FormGroup} from '@angular/forms';
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
import {SettingPermitService} from '../../permit/permit.service';
import {FlatTreeControl} from '@angular/cdk/tree';
import {MatTreeFlatDataSource, MatTreeFlattener} from '@angular/material/tree';
import {Subject} from 'rxjs';
import {takeUntil} from 'rxjs/internal/operators';
import {SelectionModel} from '@angular/cdk/collections';

// 接口
interface Role {
    id: string;
    role_name: string;
    description: string;
}

interface PermitNode {
    id: number;
    icon: string;
    method: string;
    permission_name: string;
    module: string;
    parentId: number;
    route: string;
    type: number;
    children?: PermitNode[];
}

/** Flat node with Permit and level information */
interface PermitFlatNode {
    expandable: boolean;
    id: number;
    name: string;
    routing: string;
    method: string;
    type: number;
    level: number;
}

@Component({
    selector: 'permissions-roles-form-dialog',
    templateUrl: './roles-form.component.html',
    styleUrls: ['./roles-form.component.scss'],
    encapsulation: ViewEncapsulation.None,
})

export class RolesFormDialogComponent implements OnInit, OnDestroy {
    action: string;
    role: Role = {
        'id': '',
        'role_name': '',
        'description': '',
    };
    roleForm: FormGroup;
    dialogTitle: string;
    treeControl: FlatTreeControl<PermitFlatNode>;
    treeFlattener: MatTreeFlattener<PermitNode, PermitFlatNode>;
    dataSource: MatTreeFlatDataSource<PermitNode, PermitFlatNode>;
    permit: any;
    public permits: PermitNode[];
    /** The selection for checklist */
    checklistSelection = new SelectionModel<number>(true /* multiple */);
    // Private
    private _unsubscribeAll: Subject<any>;

    /**
     * Constructor
     *
     * @param _settingPermitService
     * @param {MatDialogRef<PermitFormDialogComponent>} matDialogRef
     * @param _data
     * @param {FormBuilder} _formBuilder
     */
    constructor(
        private _settingPermitService: SettingPermitService,
        public matDialogRef: MatDialogRef<RolesFormDialogComponent>,
        @Inject(MAT_DIALOG_DATA) private _data: any,
        private _formBuilder: FormBuilder
    ) {
        this.checklistSelection.select(/* [{expandable: true,
            id: 4,
            level: 0,
            method: 'get',
            name: 'Dashboard',
            routing: 'dashboard',
            type: 1},{expandable: false,
            id: 5,
            level: 1,
            method: 'get',
            name: '主题',
            routing: 'themes',
            type: 2}] */);
        // Set the defaults
        this.action = _data.action;
        // Set the private defaults
        this._unsubscribeAll = new Subject();

        this.treeControl = new FlatTreeControl<PermitFlatNode>(
            node => node.level, node => node.expandable);

        this.treeFlattener = new MatTreeFlattener(
            ((node: PermitNode, level: number) => {
                return {
                    expandable: !!node.children && node.children.length > 0,
                    id: node.id,
                    name: node.permission_name,
                    routing: node.route,
                    method: node.method,
                    level: level,
                    type: node.type
                };
            }), node => node.level, node => node.expandable, node => node.children);

        this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);

        this._settingPermitService.onPermissionsChanged
            .pipe(takeUntil(this._unsubscribeAll))
            .subscribe(permits => {
                this.permits = permits;
                console.log(permits);
            });

        this.dataSource.data = this.permits;

        if (this.action === 'edit') {
            this.dialogTitle = '编辑角色';
            this.role = _data.role;
            console.log(this.role);
        } else {
            this.dialogTitle = '新增角色';
            // this.permit = this.permit;
        }

        this.roleForm = this.createRoleForm();

    }

    hasChild = (_: number, node: PermitFlatNode) => node.expandable;
    getLevel = (node: PermitFlatNode) => node.level;


    /** 样式--是否选择了该节点的所有子代。 */
    descendantsAllSelected(node: PermitFlatNode): boolean {
        const descendants = this.treeControl.getDescendants(node);
        return descendants.every(child =>
            this.checklistSelection.isSelected(child.id)
        );
    }

    /** 样式--是否选择了部分子代 */
    descendantsPartiallySelected(node: PermitFlatNode): boolean {
        const descendants = this.treeControl.getDescendants(node);
        const result = descendants.some(child => this.checklistSelection.isSelected(child.id));
        return result && !this.descendantsAllSelected(node);
    }

    /**
     * Toggle the to-do item selection. Select/deselect all the descendants node
     * 选择/取消选择所有子节点
     */
    todoItemSelectionToggle(node: PermitFlatNode): void {
        this.checklistSelection.toggle(node.id);
        const descendants = this.treeControl.getDescendants(node);
        // console.log(descendants.map(obj => {return obj.id}));
        this.checklistSelection.isSelected(node.id)
            ? this.checklistSelection.select(...descendants.map(obj => {
                return obj.id;
            }))
            : this.checklistSelection.deselect(...descendants.map(obj => {
                return obj.id;
            }));

        // Force update for the parent
        descendants.every(child =>
            this.checklistSelection.isSelected(child.id)
        );
        this.checkAllParentsSelection(node);
        // test
        this.selectValues();
    }

    /** Toggle a leaf to-do item selection. Check all the parents to see if they changed */
    todoLeafItemSelectionToggle(node: PermitFlatNode): void {
        this.checklistSelection.toggle(node.id);
        this.checkAllParentsSelection(node);
        // test
        this.selectValues();
    }

    /* Checks all the parents when a leaf node is selected/unselected */
    checkAllParentsSelection(node: PermitFlatNode): void {
        let parent: PermitFlatNode | null = this.getParentNode(node);
        while (parent) {
            this.checkRootNodeSelection(parent);
            parent = this.getParentNode(parent);
        }
    }

    /** Check root node checked state and change it accordingly */
    checkRootNodeSelection(node: PermitFlatNode): void {
        const nodeSelected = this.checklistSelection.isSelected(node.id);
        const descendants = this.treeControl.getDescendants(node);
        const descAllSelected = descendants.every(child =>
            this.checklistSelection.isSelected(child.id)
        );
        const descPartiallySelected = descendants.some(child =>
            this.checklistSelection.isSelected(child.id)
        );
        if (nodeSelected && !descPartiallySelected) {
            this.checklistSelection.deselect(node.id);
        } else if (!nodeSelected && descAllSelected) {
            this.checklistSelection.select(node.id);
            // 选中部分子节点是 选中所有父节点
        } else if (!nodeSelected && descPartiallySelected) {
            this.checklistSelection.select(node.id);
        }
    }

    /* Get the parent node of a node */
    getParentNode(node: PermitFlatNode): PermitFlatNode | null {
        const currentLevel = this.getLevel(node);

        if (currentLevel < 1) {
            return null;
        }

        const startIndex = this.treeControl.dataNodes.indexOf(node) - 1;

        for (let i = startIndex; i >= 0; i--) {
            const currentNode = this.treeControl.dataNodes[i];

            if (this.getLevel(currentNode) < currentLevel) {
                return currentNode;
            }
        }
        return null;
    }

    //  获取选择的permit ID
    selectValues(): void {
        if (this.checklistSelection.selected.length) {
            console.log(this.checklistSelection.selected);
        } else {
            console.log('NULL');
        }

    }

    // -----------------------------------------------------------------------------------------------------
    // @ Public methods
    // -----------------------------------------------------------------------------------------------------

    /**
     * Create contact form
     *
     * @returns {FormGroup}
     */
    createRoleForm(): FormGroup {
        return this._formBuilder.group({
            id: [this.role['id']],
            role_name: [this.role['role_name']],
            description: [this.role['description']]
        });
    }


    ngOnInit(): void {
        //  默认选择
        this.checklistSelection.select(...[33, 32, 31]);
    }

    /**
     * On destroy
     */
    ngOnDestroy(): void {
        // Unsubscribe from all subscriptions
        this._unsubscribeAll.next();
        this._unsubscribeAll.complete();
    }

}
